home *** CD-ROM | disk | FTP | other *** search
/ The CICA Windows Explosion! / The CICA Windows Explosion! - Disc 2.iso / winsock / ircii2-6.zip / SRC\IRCII-2.6\SOURCE\IRC.C < prev    next >
C/C++ Source or Header  |  1995-01-09  |  25KB  |  1,082 lines

  1. /*
  2.  * ircII: a new irc client.  I like it.  I hope you will too!
  3.  *
  4.  * Written By Michael Sandrof
  5.  * Copyright(c) 1990 
  6.  * See the COPYRIGHT file, or do a HELP IRCII COPYRIGHT 
  7.  */
  8.  
  9. #ifndef lint
  10. static    char    rcsid[] = "@(#)$Id: irc.c,v 1.58 1994/10/17 12:04:52 mrg Exp $";
  11. #endif
  12.  
  13. #define IRCII_VERSION    "2.6"
  14.  
  15. /*
  16.  * INTERNAL_VERSION is the number that the special alias $V returns.
  17.  * Make sure you are prepared for floods, pestilence, hordes of locusts, 
  18.  * and all sorts of HELL to break loose if you change this number.
  19.  * Its format is actually YYYYMMDD, for the _release_ date of the
  20.  * client..
  21.  */
  22. #define INTERNAL_VERSION    "19941018"
  23.  
  24. #include "irc.h"
  25.  
  26. #include <sys/stat.h>
  27. #ifndef __MSDOS__
  28. #include <pwd.h>
  29. #endif
  30.  
  31. #ifdef ISC22
  32. # include <sys/bsdtypes.h>
  33. #endif /* ISC22 */
  34.  
  35. #ifdef ESIX
  36. # include <lan/net_types.h>
  37. #endif /* ESIX */
  38.  
  39. #if USING_CURSES
  40. # include <curses.h>
  41. #endif /* POSIX */
  42.  
  43. #if DO_USER2
  44. # include <setjmp.h>
  45. #endif
  46.  
  47. #include "status.h"
  48. #include "dcc.h"
  49. #include "names.h"
  50. #include "vars.h"
  51. #include "input.h"
  52. #include "alias.h"
  53. #include "output.h"
  54. #include "term.h"
  55. #include "exec.h"
  56. #include "screen.h"
  57. #include "log.h"
  58. #include "server.h"
  59. #include "hook.h"
  60. #include "keys.h"
  61. #include "ircaux.h"
  62. #include "edit.h"
  63. #include "window.h"
  64. #include "history.h"
  65. #include "exec.h"
  66. #include "notify.h"
  67. #include "mail.h"
  68. #include "debug.h"
  69.  
  70. int    irc_port = IRC_PORT,            /* port of ircd */
  71.     send_text_flag = -1,            /* used in the send_text()
  72.                          * routine */
  73.     use_flow_control = USE_FLOW_CONTROL,    /* true: ^Q/^S used for flow
  74.                          * cntl */
  75.     irc_io_loop = 1,            /* see irc_io below */
  76.     break_io_processing = 0,        /* more forceful than
  77.                          * irc_io_loop */
  78.     current_numeric,            /* this is negative of the
  79.                          * current numeric! */
  80.     dumb = 0,                /* if true, IRCII is put in
  81.                          * "dumb" mode */
  82.     no_fork = 0,                /* if true, IRCII won't with
  83.                          * -b or -e */
  84.     use_input = 1,                /* if 0, stdin is never
  85.                          * checked */
  86.     waiting = 0,                /* used by /WAIT command */
  87.     who_mask = 0;                /* keeps track of which /who
  88.                          * switchs are set */
  89.  
  90. char    oper_command = 0;    /* true just after an oper() command is
  91.                  * given.  Used to tell the difference
  92.                  * between an incorrect password generated by
  93.                  * an oper() command and one generated when
  94.                  * connecting to a new server */
  95. char    global_all_off[2];        /* lame kludge to get around lameness */
  96. char    FAR MyHostName[80]  = "";    /* The local machine name. Used by
  97.                      * DCC TALK */
  98.     struct    in_addr    MyHostAddr;        /* The local machine address */
  99.     struct    in_addr    local_ip_address; /* Sometimes the same, sometimes not */
  100. extern    char    *last_away_nick;
  101.  
  102. char    *invite_channel = (char *) 0,        /* last channel of an INVITE */
  103.     FAR buffer[BIG_BUFFER_SIZE + 1] = "",    /* multipurpose buffer */
  104.     *ircrc_file = (char *) 0,        /* full path .ircrc file */
  105.     *my_path = (char *) 0,        /* path to users home dir */
  106.     *irc_path = (char *) 0,        /* paths used by /load */
  107.     *irc_lib = (char *) 0,        /* path to the ircII library */
  108.     FAR nickname[NICKNAME_LEN + 1],        /* users nickname */
  109.     FAR hostname[NAME_LEN + 1],        /* name of current host */
  110.     FAR realname[REALNAME_LEN + 1],        /* real name of user */
  111.     FAR username[NAME_LEN + 1],        /* usernameof user */
  112.     *send_umode = NULL,            /* sent umode */
  113.     *args_str = (char *) 0,        /* list of command line args */
  114.     *last_notify_nick = (char *) 0,    /* last detected nickname */
  115.     empty_string[] = "",            /* just an empty string */
  116.     *who_name = (char *) 0,        /* extra /who switch info */
  117.     *who_file = (char *) 0,        /* extra /who switch info */
  118.     *who_server = (char *) 0,        /* extra /who switch info */
  119.     *who_host = (char *) 0,        /* extra /who switch info */
  120.     *who_nick = (char *) 0,        /* extra /who switch info */
  121.     *who_real = (char *) 0,        /* extra /who switch info */
  122.     *cannot_open = (char *) 0,        /* extra /who switch info */
  123.     *cut_buffer = (char *) 0;        /* global cut_buffer */
  124.  
  125.     int away_set = 0;            /* set if there is an away
  126.                          * message anywhere */
  127.     time_t    idle_time = 0;
  128.         time_t  start_time;
  129.  
  130.     RETSIGTYPE    cntl_c();
  131.     RETSIGTYPE    sig_user1() ;
  132. #ifdef CORECATCH
  133.     RETSIGTYPE    coredump() ;
  134. #endif /* CORECATCH */
  135.  
  136. static    int    cntl_c_hit = 0;
  137.  
  138. #if DO_USER2
  139.     jmp_buf    outta_here;
  140. #endif
  141.  
  142.     char    irc_version[] = IRCII_VERSION;
  143.     char    internal_version[] = INTERNAL_VERSION;
  144.  
  145. static    char    FAR switch_help[] =
  146. "Usage: irc [switches] [nickname] [server list] \n\
  147.   The [nickname] can be at most 9 characters long\n\
  148.   The [server list] is a whitespace separate list of server name\n\
  149.   The [switches] may be any or all of the following\n\
  150.    -c <channel>\tjoins <channel> o startup\n\
  151.    -p <port>\tdefault server connection port (usually 6667)\n\
  152.    -f\t\tyour terminal uses flow controls (^S/^Q), so IRCII shouldn't\n\
  153.    -F\t\tyour terminal doesn't use flow control (default)\n\
  154.    -s\t\tdon't use separate server processes (ircserv)\n\
  155.    -S\t\tuse separate server processes (ircserv)\n\
  156.    -d\t\truns IRCII in \"dumb\" terminal mode\n\
  157.    -a\t\tadds default servers and command line servers to server list\n";
  158.  
  159. static    char    FAR switch_help_l[] =
  160. #ifdef COMMAND_LINE_L
  161. "   -l <file>\tloads <file> in place of your .ircrc\n\
  162.    -L <file>\tloads <file> in place of your .ircrc and expands $ expandos\n";
  163. #else
  164. "";
  165. #endif
  166.  
  167. /* irc_exit: cleans up and leaves */
  168. void
  169. irc_exit()
  170. {
  171. do_hook(EXIT_LIST,"Exiting");
  172.     close_server(-1, "Leaving");
  173.     logger(0);
  174.     set_history_file((char *) 0);
  175. #ifndef _Windows
  176.     clean_up_processes();
  177. #endif
  178.     if (!dumb)
  179.     {
  180.         cursor_to_input();    /* Needed so that ircII doesn't gobble
  181.                      * the last line of the kill. */
  182.         term_cr();
  183.         if (term_clear_to_eol())
  184.             term_space_erase(0);
  185.         term_reset();
  186. #if defined(_HPUX_SOURCE) || defined(ESIX)
  187.         endwin();        /* Added for curses */
  188. #ifdef ESIX
  189.         system("tput reset");
  190.         new_stty("sane");
  191. #endif /* ESIX */
  192. #endif /* defined(_HPUX_SOURCE) || defined(ESIX) */
  193.     }
  194.     exit(0);
  195. }
  196.  
  197. #ifdef CORECATCH
  198. /* sigsegv: something to handle segfaults in a nice way */
  199. RETSIGTYPE
  200. coredump(sig)
  201.     int    sig;
  202. {
  203.     printf("IRCII has been terminated by a SIG%s\n\r", signals[sig]);
  204.     printf("Please inform phone (phone@coombs.anu.edu.au) of this\n\r");
  205.     printf("with as much detail as possible about what you were doing when it happened.\n\r");
  206.     printf("Please include the version of IRCII (%s) and type of system in the report.\n\r", irc_version);
  207.     fflush(stdout);
  208.     irc_exit();
  209. }
  210. #endif
  211.  
  212. /*
  213.  * quit_response: Used by irc_io when called from irc_quit to see if we got
  214.  * the right response to our question.  If the response was affirmative, the
  215.  * user gets booted from irc.  Otherwise, life goes on. 
  216.  */
  217. static    void
  218. quit_response(dummy, ptr)
  219.     char    *dummy;
  220.     char    *ptr;
  221. {
  222.     int    len,
  223.         old_irc_io_loop;
  224.  
  225.     old_irc_io_loop = irc_io_loop;
  226.     irc_io_loop = 0;
  227.     if ((len = strlen(ptr)) != 0)
  228.     {
  229.         if (!my_strnicmp(ptr, "yes", len))
  230.         {
  231.             send_to_server("QUIT");
  232.             irc_exit();
  233.         }
  234.     }
  235.     irc_io_loop = old_irc_io_loop;
  236. }
  237.  
  238. /* irc_quit: prompts the user if they wish to exit, then does the right thing */
  239. void
  240. irc_quit()
  241. {
  242.     static    int in_it = 0;
  243.  
  244.     if (in_it)
  245.         return;
  246.     in_it = 1;
  247.     add_wait_prompt("Do you really want to quit? ", quit_response,
  248.         empty_string, WAIT_PROMPT_LINE);
  249.     in_it = 0;
  250. }
  251.  
  252. /*
  253.  * cntl_c: emergency exit.... if somehow everything else freezes up, hitting
  254.  * ^C five times should kill the program. 
  255.  */
  256. RETSIGTYPE
  257. cntl_c()
  258. {
  259. #ifdef SYSVSIGNALS
  260.     (void) MY_SIGNAL(SIGINT, cntl_c, 0);
  261. #endif /* SYSVSIGNALS */
  262.     if (cntl_c_hit++ >= 4)
  263.         irc_exit();
  264. }
  265.  
  266. RETSIGTYPE
  267. sig_user1()
  268. {
  269. #ifdef SYSVSIGNALS
  270.     (void) MY_SIGNAL(SIGUSR1, sig_user1, 0);
  271. #endif /* SYSVSIGNALS */
  272.     say("Got SIGUSR1, closing DCC connections and EXECed processes");
  273.     close_all_dcc();
  274. #ifndef _Windows
  275.     close_all_exec();
  276. #endif
  277. }
  278.  
  279. #if DO_USER2
  280. RETSIGTYPE
  281. sig_user2()
  282. {
  283. #ifdef SYSVSIGNALS
  284.     (void) MY_SIGNAL(SIGUSR2, sig_user2, 0);
  285. #endif /* SYSVSIGNALS */
  286.     say("Got SIGUSR2, jumping to normal loop");
  287.     longjmp(outta_here);
  288. }
  289. #endif 
  290.  
  291. #ifdef MUNIX
  292. /* A characteristic of PCS MUNIX - Ctrl-Y produces a SIGQUIT */
  293. RETSIGTYPE
  294. cntl_y()
  295. {
  296.     (void) MY_SIGNAL(SIGQUIT, cntl_y, 0);
  297.     edit_char((char) 25); /* Ctrl-Y */
  298. }
  299. #endif
  300.  
  301. /* shows the version of irc */
  302. static    void
  303. show_version()
  304. {
  305.     printf("ircII version %s (%s)\n\r", irc_version, internal_version);
  306.     exit (0);
  307. }
  308.  
  309. /* get_arg: used by parse_args() to get an argument after a switch */
  310. static    char    *
  311. get_arg(arg, next_arg, ac)
  312.     char    *arg;
  313.     char    *next_arg;
  314.     int    *ac;
  315. {
  316.     (*ac)++;
  317.     if (*arg)
  318.         return (arg);
  319.     else
  320.     {
  321.         if (next_arg)
  322.             return (next_arg);
  323.         fprintf(stderr, "irc: missing parameter\n");
  324.         exit(1);
  325.     }
  326. }
  327.  
  328. /*
  329.  * parse_args: parse command line arguments for irc, and sets all initial
  330.  * flags, etc. 
  331.  */
  332. static    char    *
  333. parse_args(argv, argc)
  334.     char    *argv[];
  335.     int    argc;
  336. {
  337.     char    *arg,
  338.         *ptr;
  339.     int    ac;
  340.     int    add_servers = 0;
  341.     char    *channel = (char *) NULL;
  342.     struct    passwd    *entry;
  343.     struct    hostent    *hp;
  344.  
  345.     /*
  346.      * Note that this uses the global buffer to build the args_str list,
  347.      * which is a whitespace separated list of the arguments used when
  348.      * loading the .ircrc and GLOBAL_IRCRC files.
  349.      */
  350.     *nickname = '\0';
  351.     *realname = '\0';
  352.     ac = 1;
  353.     strmcpy(buffer, argv[0], BIG_BUFFER_SIZE);
  354.     strmcat(buffer, " ", BIG_BUFFER_SIZE);
  355.     while ((arg = argv[ac++]) != (char *) NULL)
  356.     {
  357.         strmcat(buffer, argv[ac-1], BIG_BUFFER_SIZE);
  358.         strmcat(buffer, " ", BIG_BUFFER_SIZE);
  359.         if ((*arg == '-') != '\0')
  360.         {
  361.             ++arg;
  362.             while (*arg)
  363.             {
  364.                 switch (*(arg++))
  365.                 {
  366.                 case 'v':
  367.                     show_version();
  368.                     break;
  369.                 case 'c':
  370.                     malloc_strcpy(&channel, get_arg(arg,
  371.                             argv[ac], &ac));
  372.                     break;
  373.                 case 'p':
  374.                     irc_port = atoi(get_arg(arg, argv[ac],
  375.                             &ac));
  376.                     break;
  377.                 case 'f':
  378.                     use_flow_control = 1;
  379.                     break;
  380.                 case 'F':
  381.                     use_flow_control = 0;
  382.                     break;
  383.                 case 'd':
  384.                     dumb = 1;
  385.                     break;
  386. #ifdef DEBUG
  387.                 case 'D':
  388.                     setdlevel(atoi(get_arg(arg, argv[ac],
  389.                         &ac)));
  390.                     break;
  391.                 case 'o':
  392.                     {
  393.                         FILE    *fp;
  394.                         char    *file = get_arg(arg, argv[ac], &ac);
  395.  
  396.                         if (!file)
  397.                         {
  398.                             printf("irc: need filename for -o\n");
  399.                             exit(-1);
  400.                         }
  401.                         fp = freopen(file, "w", stderr);
  402.                         if (!fp)
  403.                         {
  404.                             printf("irc: can not open %s: %s\n", file, errno ? "" : strerror(errno));
  405.                             exit(-1);
  406.                         }
  407.                     }
  408. #endif /* DEBUG */
  409. #ifdef COMMAND_LINE_L
  410.                 case 'l':
  411.                     malloc_strcpy(&ircrc_file, get_arg(arg,
  412.                             argv[ac], &ac));
  413.                     break;
  414.                 case 'L':
  415.                     malloc_strcpy(&ircrc_file, get_arg(arg,
  416.                             argv[ac], &ac));
  417.                     malloc_strcat(&ircrc_file," -");
  418.                     break;
  419. #endif /* COMMAND_LINE_L */
  420.                 case 'a':
  421.                     add_servers = 1;
  422.                     break;
  423.                 case 's':
  424.                     using_server_process = 0;
  425.                     break;
  426.                 case 'S':
  427.                     using_server_process = 1;
  428.                     break;
  429.                 case '-':
  430.                     while ((arg = argv[ac++]) != NULL)
  431.                     {
  432.                         strmcat(command_line, arg,
  433.                             BIG_BUFFER_SIZE);
  434.                         strmcat(command_line, " ",
  435.                             BIG_BUFFER_SIZE);
  436.                     }
  437.                     if (*command_line)
  438.                 command_line[strlen(command_line)-1] = '\0';
  439.                     break;
  440.                 default:
  441.                     fprintf(stderr, "%s%s", switch_help, switch_help_l);
  442.                     exit(1);
  443.                 }
  444.             }
  445.         }
  446.         else
  447.         {
  448.             if (*nickname)
  449.                 build_server_list(arg);
  450.             else
  451.                 strmcpy(nickname, arg, NICKNAME_LEN);
  452.         }
  453.     }
  454.     malloc_strcpy(&args_str, buffer);
  455.     if ((char *) 0 != (ptr = (char *) getenv("IRCLIB")))
  456.     {
  457.         malloc_strcpy(&irc_lib, ptr);
  458.         malloc_strcat(&irc_lib, "/");
  459.     }
  460.     else
  461.         malloc_strcpy(&irc_lib, IRCLIB);
  462.  
  463.     if ((char *) 0 == ircrc_file && (char *) 0 != (ptr = getenv("IRCRC")))
  464.         malloc_strcpy(&ircrc_file, ptr);
  465.  
  466.     if (*nickname == '\0' && (char *) 0 != (ptr = getenv("IRCNICK")))
  467.         strmcpy(nickname, ptr, NICKNAME_LEN);
  468.  
  469.     if ((char *) 0 != (ptr = getenv("IRCUMODE")))
  470.         malloc_strcpy(&send_umode, ptr);
  471.  
  472.     if ((char *) 0 != (ptr = getenv("IRCNAME")))
  473.         strmcpy(realname, ptr, REALNAME_LEN);
  474.  
  475.     if ((char *) 0 != (ptr = getenv("IRCPATH")))
  476.         malloc_strcpy(&irc_path, ptr);
  477.     else
  478.     {
  479. #ifdef IRCPATH
  480.         malloc_strcpy(&irc_path, IRCPATH);
  481. #else
  482. #ifdef __MSDOS__
  483.         malloc_strcpy(&irc_path, ".:~/irc:");
  484. #else
  485.         malloc_strcpy(&irc_path, ".:~/.irc:");
  486. #endif
  487.         malloc_strcat(&irc_path, irc_lib);
  488.         malloc_strcat(&irc_path, "script");
  489. #endif
  490.     }
  491.  
  492.     set_string_var(LOAD_PATH_VAR, irc_path);
  493.     new_free(&irc_path);
  494.     if ((char *) 0 != (ptr = getenv("IRCSERVER")))
  495.         build_server_list(ptr);
  496.     if (0 == server_list_size() || add_servers)
  497.     {
  498. #ifdef SERVERS_FILE
  499.         if (read_server_file() || (server_list_size() == 0))
  500. #endif
  501.         {
  502.             char *ptr = (char *) 0;
  503.  
  504. #ifdef _Windows
  505.             GetPrivateProfileString("Defaults", "Server",
  506.                         "You.Need.To.Edit.IRCII.INI",
  507.                         buffer, sizeof(buffer), "IRCII.INI");
  508.             malloc_strcpy(&ptr, buffer);
  509. #else
  510.             malloc_strcpy(&ptr, DEFAULT_SERVER);
  511. #endif
  512.             build_server_list(ptr);
  513.             new_free(&ptr);
  514.         }
  515.     }
  516. #ifdef _Windows
  517.     if (!*nickname)
  518.         GetPrivateProfileString("Defaults", "Nick", "ircuser", nickname, NICKNAME_LEN + 1, "IRCII.INI");
  519.     GetPrivateProfileString("UserNames", nickname, nickname, username, NAME_LEN + 1, "IRCII.INI");
  520.     GetPrivateProfileString("RealNames", username, username, realname, REALNAME_LEN + 1, "IRCII.INI");
  521.     GetPrivateProfileString("Directories", username, get_path(4), buffer, BIG_BUFFER_SIZE, "IRCII.INI");
  522.     malloc_strcpy(&my_path, buffer);
  523. #else /* _Windows */
  524.     if ((struct passwd *) 0 != (entry = getpwuid(getuid())))
  525.     {
  526.         if ((*realname == '\0') && entry->pw_gecos && *(entry->pw_gecos))
  527.         {
  528. #ifdef GECOS_DELIMITER
  529.             if ((ptr = index(entry->pw_gecos, GECOS_DELIMITER)) 
  530.                     != NULL)
  531.                 *ptr = '\0';
  532. #endif /* GECOS_DELIMITER */
  533.             strmcpy(realname, entry->pw_gecos, REALNAME_LEN);
  534.         }
  535.         if (entry->pw_name && *(entry->pw_name))
  536.             strmcpy(username, entry->pw_name, NAME_LEN);
  537.  
  538.         if (entry->pw_dir && *(entry->pw_dir))
  539.             malloc_strcpy(&my_path, entry->pw_dir);
  540.     }
  541. #endif /* _Windows */
  542.     if ((char *) 0 != (ptr = getenv("HOME")))
  543.         malloc_strcpy(&my_path, ptr);
  544.     else if (*my_path == '\0')
  545.         malloc_strcpy(&my_path, "/");
  546.  
  547.     if ('\0' == *realname)
  548.         strmcpy(realname, "*Unknown*", REALNAME_LEN);
  549.  
  550.     if ('\0' == *username)
  551.     {
  552.         if ((ptr = getenv("USER")) != NULL)
  553.             strmcpy(username, ptr, NAME_LEN);
  554.         else
  555.             strmcpy(username, "Unknown", NAME_LEN);
  556.     }
  557.     gethostname(MyHostName, sizeof(MyHostName));
  558.     if ((hp = gethostbyname(MyHostName)) != NULL)
  559.     {
  560.         bcopy(hp->h_addr, (char *) &MyHostAddr, sizeof(MyHostAddr));
  561.         local_ip_address.s_addr = ntohl(MyHostAddr.s_addr);
  562.     }
  563.     if (*nickname == '\0')
  564.         strmcpy(nickname, username, NICKNAME_LEN);
  565.     if (0 == check_nickname(nickname))
  566.     {
  567.         fprintf(stderr, "Illegal nickname %s\n", nickname);
  568.         exit(1);
  569.     }
  570.     if ((char *) 0 == ircrc_file)
  571.     {
  572.         ircrc_file = (char *) new_malloc(strlen(my_path) +
  573.             strlen(IRCRC_NAME) + 1);
  574.         strcpy(ircrc_file, my_path);
  575.         strcat(ircrc_file, IRCRC_NAME);
  576.     }
  577.     return (channel);
  578. }
  579.  
  580. /*
  581.  * TimerTimeout:  Called from irc_io to help create the timeout
  582.  * part of the call to select.
  583.  */
  584. time_t
  585. TimerTimeout()
  586. {
  587.     time_t    current;
  588.     time_t    timeout_in;
  589.  
  590.     if (!PendingTimers)
  591.         return 70; /* Just larger than the maximum of 60 */
  592.     time(¤t);
  593.     timeout_in = PendingTimers->time - current;
  594.     return (timeout_in < 0) ? 0 : timeout_in;
  595. }
  596.  
  597. /*
  598.  * irc_io: the main irc input/output loop.   Handles all io from keyboard,
  599.  * server, exec'd processes, etc.  If a prompt is specified, it is displayed
  600.  * in the input line and cannot be backspaced over, etc. The func is a
  601.  * function which will take the place of the SEND_LINE function (which is
  602.  * what happens when you hit return at the end of a line). This function must
  603.  * decide if it's ok to exit based on anything you really want.  It can then
  604.  * set the global irc_io_loop to false to cause irc_io to exit. 
  605.  */
  606. int
  607. irc_io(prompt, func, use_input, loop)
  608.     char    *prompt;
  609.     void    (*func) ();
  610.     int    use_input;
  611.     int    loop;
  612. {
  613.     static    int    level = 0;
  614.     fd_set    rd,
  615.         wd;
  616.     define_big_buffer(buffer);    /* buffer much bigger than
  617.                      * IRCD_BUFFER_SIZE */
  618.     struct    timeval cursor_timeout,
  619.         clock_timeout,
  620.         right_away,
  621.         timer,
  622.         *timeptr;
  623.     int    hold_over;
  624.     int    old_loop;
  625.     char    *last_input = NULL;
  626.     char    *last_prompt = NULL;
  627.     void    (*last_func)();
  628.     int    one_key = 0;
  629.     Screen    *screen,
  630.         *old_current_screen;
  631.  
  632.     last_func = get_send_line();
  633.     if (use_input == -1)
  634.         one_key = 1, prompt = NULL;
  635. #ifdef    PRIV_PORT_ULC
  636.     seteuid(getuid());
  637. #endif
  638.     /* time before cursor jumps from display area to input line */
  639.     cursor_timeout.tv_usec = 0L;
  640.     cursor_timeout.tv_sec = 1L;
  641.  
  642.     /* time delay for updating of internal clock */
  643.     clock_timeout.tv_usec = 0L;
  644.     clock_timeout.tv_sec = 30L;
  645.  
  646.     right_away.tv_usec = 0L;
  647.     right_away.tv_sec = 0L;
  648.  
  649.     timer.tv_usec = 0L;
  650.  
  651.     old_loop = irc_io_loop;
  652.     irc_io_loop = loop;
  653.  
  654.             /*
  655.     if (level++ > 20)
  656.              * irc_io has been recursive to date.
  657.              * with multiple xterms and screen
  658.              * windows, this has to change
  659.              */
  660.     if (level++ > 5)
  661.     {
  662.         level--;
  663.         irc_io_loop = old_loop;
  664.         free_big_buffer(buffer);
  665.         return (1);
  666.     }
  667.     if (!dumb)
  668.     {
  669.         if (use_input)
  670.         {
  671.             malloc_strcpy(&last_input, get_input());
  672.             set_input(empty_string);
  673.             last_func = get_send_line();
  674.             change_send_line(func);
  675.         }
  676.         if (prompt)
  677.         {
  678.             malloc_strcpy(&last_prompt, get_input_prompt());
  679.             set_input_prompt(prompt);
  680.         }
  681.     }
  682.     /*
  683.      * Here we work out if this has been called recursively or
  684.      * not..  and if not so.. -phone
  685.      */
  686.  
  687. #if defined(DEBUG) || defined(DO_USER2)
  688.     if (level != 1)
  689.     {
  690. #ifdef DEBUG
  691.         yell("--- Recursive call to irc_io() - careful");
  692. #endif /* DEBUG */
  693.     }
  694.     else
  695.     {
  696. #if DO_USER2
  697.         if (setjmp(outta_here))
  698.             yell("*** Got SIGUSR2, Aborting");
  699. #endif /* DO_USER2 */
  700.     }
  701. #endif /* DEBUG || DO_USER2 */
  702.  
  703.     timeptr = &clock_timeout;
  704.     do
  705.     {
  706.         break_io_processing = 0;
  707.         FD_ZERO(&rd);
  708.         FD_ZERO(&wd);
  709. #ifndef _Windows
  710.         if (use_input)
  711.             for (screen = screen_list;screen; screen = screen->next)
  712.                 if (screen->alive)
  713.                     FD_SET(screen->fdin, &rd);
  714. #endif
  715.         set_server_bits(&rd);
  716.         set_dcc_bits(&rd, &wd);
  717. #ifndef _Windows
  718.         set_process_bits(&rd);
  719.         if (term_reset_flag)
  720.         {
  721.             refresh_screen();
  722.             term_reset_flag = 0;
  723.         }
  724. #endif
  725.         timer.tv_sec = TimerTimeout();
  726.         if (timer.tv_sec <= timeptr->tv_sec)
  727.             timeptr = &timer;
  728.         if ((hold_over = unhold_windows()) != 0)
  729.             timeptr = &right_away;
  730.         Debug((7, "irc_io: selecting with %l:%l timeout", timeptr->tv_sec,
  731.             timeptr->tv_usec));
  732.         switch (new_select(&rd, &wd, timeptr))
  733.         {
  734.         case 0:
  735.         case -1:
  736.             if (cntl_c_hit)
  737.             {
  738.                 if (one_key)
  739.                 {
  740.                     irc_io_loop = 0;
  741.                     break;
  742.                 }
  743.                 edit_char('\003');
  744.                 cntl_c_hit = 0;
  745.             }
  746.             if (!hold_over)
  747.                 cursor_to_input();
  748.             break;
  749.         default:
  750. #ifndef _Windows
  751.             if (term_reset_flag)
  752.             {
  753.                 refresh_screen();
  754.                 term_reset_flag = 0;
  755.             }
  756. #endif
  757.             old_current_screen = current_screen;
  758.             set_current_screen(last_input_screen);
  759.             if (!break_io_processing)
  760.                 dcc_check(&rd);
  761.             if (!break_io_processing)
  762.                 do_server(&rd);
  763.             set_current_screen(old_current_screen);
  764.             for (screen = screen_list; screen &&
  765.                 !break_io_processing; screen = screen->next)
  766.             {
  767.                 if (!screen->alive)
  768.                     continue;
  769.                 set_current_screen(screen);
  770.                 if (FD_ISSET(screen->fdin, &rd))
  771.                 {
  772.  
  773.     /*
  774.      * This section of code handles all in put from the terminal(s).
  775.      * connected to ircII.  Perhaps the idle time *shouldn't* be 
  776.      * reset unless its not a screen-fd that was closed..
  777.      *
  778.      * This section indented - phone, jan 1993
  779.      */
  780.  
  781.             idle_time = time(0);
  782.             if (dumb)
  783.             {
  784.                 int     old_timeout;
  785.  
  786.                 old_timeout = dgets_timeout(1);
  787.                 if (dgets(buffer, INPUT_BUFFER_SIZE,
  788.                         screen->fdin, (char *) 0))
  789.                 {
  790.                     (void) dgets_timeout(old_timeout);
  791.                     if (one_key)
  792.                     {
  793.                         irc_io_loop = 0;
  794.                         break;
  795.                     }
  796.                     *(buffer + strlen(buffer) - 1) = '\0';
  797.                     if (get_int_var(INPUT_ALIASES_VAR))    
  798.                         parse_line(NULL, buffer,
  799.                             empty_string, 1, 0);
  800.                     else
  801.                         parse_line(NULL, buffer,
  802.                             NULL, 1, 0);
  803.                 }
  804.                 else
  805.                 {
  806.                     say("IRCII exiting on EOF from stdin");
  807.                     irc_exit();
  808.                 }
  809.             }
  810.             else
  811.             {
  812.                 int server;
  813.                 char    loc_buffer[BIG_BUFFER_SIZE + 1];
  814.                 int    n, i;
  815.  
  816.                 server = from_server;
  817.                 from_server = get_window_server(0);
  818.                 last_input_screen = screen;
  819.                 if (one_key)
  820.                 {
  821.                     if (read(screen->fdin, buffer, 1))
  822.                     {
  823.                         irc_io_loop = 0;
  824.                         break;
  825.                     }
  826.                     else
  827.                     {
  828. #ifndef _Windows
  829.                         if (!is_main_screen(screen))
  830.                             kill_screen(screen);
  831.                         else
  832. #endif
  833.                             irc_exit();
  834.                     }
  835.                 }
  836.                 else if ((n = read(screen->fdin, loc_buffer,
  837.                         BIG_BUFFER_SIZE)) != 0)
  838.                     for (i = 0; i < n; i++)
  839.                         edit_char(loc_buffer[i]);
  840.         /*
  841.          * if the current screen isn't the main  screen,
  842.          * then the socket to the current screen must have
  843.          * closed, so we call kill_screen() to handle 
  844.          * this - phone, jan 1993.
  845.          * but not when we arent running windows - Fizzy, may 1993
  846.          * if it is the main screen we got an EOF on, we exit..
  847.          * closed tty -> chew cpu -> bad .. -phone, july 1993.
  848.          */
  849. #ifdef WINDOW_CREATE
  850.                 else
  851.                 {
  852.                     if (!is_main_screen(screen))
  853.                         kill_screen(screen);
  854.                     else
  855.                         irc_exit();
  856.                 }
  857. #endif /* WINDOW_CREATE */
  858.                 cntl_c_hit = 0;
  859.                 from_server = server;
  860.             }
  861.  
  862.         /* End of intendation */
  863.  
  864.                 }
  865.             }
  866.             set_current_screen(old_current_screen);
  867. #ifndef _Windows
  868.             if (!break_io_processing)
  869.                 do_processes(&rd);
  870. #endif
  871.             break;
  872.         }
  873.         ExecuteTimers();
  874. #ifndef _Windows
  875.         check_process_limits();
  876.         check_wait_status();
  877. #endif
  878. /*        if ((primary_server == -1) && !never_connected)
  879.             do_hook(DISCONNECT_LIST, "%s", nickname); */
  880.         timeptr = &clock_timeout;
  881.  
  882.         old_current_screen = current_screen;
  883.         for (current_screen = screen_list; current_screen;
  884.                 current_screen = current_screen->next)
  885.             if (current_screen->alive && is_cursor_in_display())
  886.                 timeptr = &cursor_timeout;
  887.         set_current_screen(old_current_screen);
  888.  
  889.         if (update_clock(0))
  890.         {
  891.             if (get_int_var(CLOCK_VAR) || check_mail_status())
  892.             {
  893.                 status_update(1);
  894.                 cursor_to_input();
  895.             }
  896.             do_notify();
  897.         }
  898.     }
  899.     while (irc_io_loop);
  900.     level--;
  901.     irc_io_loop = old_loop;
  902.     if (! dumb)
  903.     {
  904.         if (use_input)
  905.         {
  906.             set_input(last_input);
  907.             new_free(&last_input);
  908.             change_send_line(last_func);
  909.         }
  910.         if (prompt)
  911.         {
  912.             if (level == 0)
  913.                 set_input_prompt(get_string_var(INPUT_PROMPT_VAR));
  914.             else
  915.                 set_input_prompt(last_prompt);
  916.             new_free(&last_prompt);
  917.         }
  918.     }
  919.     update_input(UPDATE_ALL);
  920.     free_big_buffer(buffer);
  921.     return (0);
  922. }
  923.  
  924. #ifdef _Windows
  925. void
  926. old_main(int argc, char **argv)
  927. #else
  928. /*ARGSUSED*/
  929. void
  930. main(argc, argv, envp)
  931.     int    argc;
  932.     char    *argv[];
  933.     char    *envp[];
  934. #endif
  935. {
  936.     char    *channel;
  937.  
  938.     reset_pointers();
  939.     start_time = time((time_t *)0);
  940.     channel = parse_args(argv, argc);
  941. #if defined(_HPUX_SOURCE) || defined(ESIX)
  942.     /* Curses code added for HP-UX use */
  943.     if (!dumb)
  944.     {
  945.         initscr();
  946.         noecho();
  947.         cbreak();
  948.     }
  949. #endif /* _HPUX_SOURCE || ESIX */
  950. #ifndef _Windows
  951.     if ((use_input == 0) && !no_fork)
  952.     {
  953.         if (fork())
  954.             _exit(0);
  955.     }
  956. #endif
  957. #ifdef ESIX
  958.     if (gethostname(hostname, NAME_LEN) == NULL)
  959. #else
  960.     if (gethostname(hostname, NAME_LEN))
  961. #endif /* ESIX */
  962.     {
  963. #ifdef _Windows
  964.         MessageBox(0, "Couldn't get host name", 0, MB_OK);
  965. #else
  966.         fprintf(stderr, "irc: couldn't figure out the name of your machine!\n");
  967.         exit(1);
  968. #endif
  969.     }
  970.     if (dumb)
  971.         new_window();
  972.     else
  973.     {
  974.         init_screen();
  975. #ifndef _Windows
  976. #if !defined(MUNIX) && !defined(_RT) && !defined(ESIX)
  977.         (void) MY_SIGNAL(SIGCONT, term_cont, 0);
  978. #endif /* !defined(MUNIX) && !defined(_RT) && !defined(ESIX) */
  979. #if !defined(_RT) && defined(SIGWINCH)
  980.         (void) MY_SIGNAL(SIGWINCH, refresh_screen, 0);
  981. #endif /* _RT */
  982. #ifndef ALLOC_DEBUG
  983. # ifdef CORECATCH
  984.         (void) MY_SIGNAL(SIGSEGV, coredump, 0);
  985. #  ifdef SIGBUS
  986.         (void) MY_SIGNAL(SIGBUS, coredump, 0);
  987. #  endif
  988. # else
  989.         (void) MY_SIGNAL(SIGSEGV, SIG_DFL, 0);
  990.         /* Linux doesn't have SIGBUS */
  991. #  ifndef SIGBUS
  992.         (void) MY_SIGNAL(SIGBUS, SIG_DFL, 0);
  993. #  endif /* SIGBUS */
  994. # endif /* CORECATCH */
  995. #endif /* ALLOC_DEBUG */
  996. #ifdef MUNIX
  997.         (void) MY_SIGNAL(SIGQUIT, cntl_y, 0);
  998. #endif
  999.         (void) MY_SIGNAL(SIGHUP, irc_exit, 0);
  1000.         (void) MY_SIGNAL(SIGTERM, irc_exit, 0);
  1001.         (void) MY_SIGNAL(SIGPIPE, SIG_IGN, 0);
  1002.         (void) MY_SIGNAL(SIGINT, cntl_c, 0);
  1003. #ifdef SIGSTOP
  1004.         (void) MY_SIGNAL(SIGSTOP, SIG_IGN, 0);
  1005. #endif
  1006.         (void) MY_SIGNAL(SIGUSR1, sig_user1, 0);
  1007. #if DO_USER2
  1008.         (void) MY_SIGNAL(SIGUSR2, sig_user2, 0);
  1009. #endif
  1010. #endif /* _Windows */
  1011.     }
  1012. #ifdef _HPUX_SOURCE
  1013.     new_stty("opost");
  1014. #endif /* _HPUX_SOURCE */
  1015.  
  1016.     init_variables();
  1017.  
  1018.     if (!dumb)
  1019.     {
  1020.         build_status((char *) 0);
  1021.         update_input(UPDATE_ALL);
  1022.     }
  1023.  
  1024. #ifdef MOTD_FILE
  1025.     {
  1026.         struct    stat    motd_stat,
  1027.                 my_stat;
  1028.         char    *motd = NULL;
  1029.         int    des;
  1030.  
  1031.         malloc_strcpy(&motd, irc_lib);
  1032.         malloc_strcat(&motd, MOTD_FILE);
  1033.         if (stat_file(motd, &motd_stat) == 0)
  1034.         {
  1035.             strmcpy(buffer, my_path, BIG_BUFFER_SIZE);
  1036. #ifdef __MSDOS__
  1037.             strmcat(buffer, "/ircmotd.red", BIG_BUFFER_SIZE);
  1038. #else
  1039.             strmcat(buffer, "/.ircmotd", BIG_BUFFER_SIZE);
  1040. #endif
  1041.             if (stat_file(buffer, &my_stat))
  1042.             {
  1043.                 my_stat.st_atime = 0L;
  1044.                 my_stat.st_mtime = 0L;
  1045.             }
  1046.             unlink(buffer);
  1047.             if ((des = open(buffer, O_CREAT, S_IREAD | S_IWRITE))
  1048.                     != -1)
  1049.                 close(des);
  1050.             if (motd_stat.st_mtime > my_stat.st_mtime)
  1051.             {
  1052.                 put_file(motd);
  1053.         /* Thanks to Mark Dame <mdame@uceng.ec.edu> for this one */
  1054.  
  1055. #if PAUSE_AFTER_MOTD
  1056.         input_pause("********  Press any key to continue  ********");
  1057. #endif
  1058.                 clear_window_by_refnum(0);
  1059.             }
  1060.         }
  1061.         new_free(&motd);
  1062.     }
  1063. #endif /* MOTD_FILE */
  1064.  
  1065.     global_all_off[0] = ALL_OFF;
  1066.     global_all_off[1] = '\0';
  1067.     get_connected(0);
  1068.     if (channel)
  1069.     {
  1070.         set_channel_by_refnum(0, channel);
  1071.         add_channel(channel, primary_server);
  1072.         new_free(&channel);
  1073.     }
  1074.     idle_time = time(0);
  1075.     set_input(empty_string);
  1076. #ifndef _Windows
  1077.     irc_io(get_string_var(INPUT_PROMPT_VAR), NULL, use_input, irc_io_loop);
  1078.     irc_exit();
  1079. #endif
  1080.     return;
  1081. }
  1082.